#include <memory>
#include <simulator/llvmJit/llvmJit.h>

std::unique_ptr<llvm::Module> LLVMJit::extraCurModule() {
    return std::move(m_module);
}

std::shared_ptr<llvm::IRBuilder<>> LLVMJit::getIrBuilder() {
    return m_irBuilder;
}

void LLVMJit::addCurModuleToJit() {
    m_ee->addModule(std::move(m_module));
}

void LLVMJit::initializeModule(const char *moduleName) {
    m_module.reset();
    m_module = std::make_unique<llvm::Module>(moduleName, *m_llvmContext);
}

LLVMJit::LLVMJit() {
    // 初始化llvm上下文和ir生成器
    m_llvmContext = std::make_unique<llvm::LLVMContext>();
    m_irBuilder = std::make_shared<llvm::IRBuilder<>>(*m_llvmContext);
    // 初始化一个空模块，用于创建jit构建类
    m_module = std::make_unique<llvm::Module>("init", *m_llvmContext);
    // 初始化jit的目标机器、汇编打印器、汇编解析器
    llvm::InitializeNativeTarget();
    LLVMInitializeNativeAsmPrinter();
    llvm::InitializeNativeTargetAsmParser();
    LLVMLinkInMCJIT();
    // 初始化jit构建类
    m_engineBuilder = std::make_shared<llvm::EngineBuilder>(std::move(m_module));
    // 初始化jit执行引擎，优化级别为O3
    auto eeObj = m_engineBuilder->setEngineKind(llvm::EngineKind::JIT).setOptLevel(
            llvm::CodeGenOpt::Default).create();
    std::unique_ptr<llvm::ExecutionEngine> eeTemp(eeObj);
    m_ee = std::move(eeTemp);
}

llvm::LLVMContext *LLVMJit::getLLVMContext() {
    return m_llvmContext.get();
}

std::shared_ptr<llvm::ExecutionEngine> LLVMJit::getExecutionEngine() {
    return m_ee;
}

llvm::Module *LLVMJit::getCurModulePtr() {
    return m_module.get();
}
